package cn.whpu.omnitrixerp.service.auth.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.whpu.omnitrixerp.entity.dto.auth.LoginReqDTO;
import cn.whpu.omnitrixerp.entity.dto.auth.LoginRespDTO;
import cn.whpu.omnitrixerp.entity.dto.auth.UserDTO;
import cn.whpu.omnitrixerp.entity.po.auth.RolePO;
import cn.whpu.omnitrixerp.entity.po.auth.UserPO;
import cn.whpu.omnitrixerp.enums.ENBool;
import cn.whpu.omnitrixerp.mapper.auth.RoleMapper;
import cn.whpu.omnitrixerp.mapper.auth.UserMapper;
import cn.whpu.omnitrixerp.service.auth.UserService;
import cn.whpu.omnitrixerp.util.JwtUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsPasswordService;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;

import java.util.Date;
import java.util.List;

/**
 * @author BruceKai
 * @description 针对表【sys_user(用户表)】的数据库操作Service实现
 * @createDate 2025-06-28 20:47:47
 */
@Service
public class UserServiceImpl implements UserService, UserDetailsService, UserDetailsPasswordService {

    @Autowired
    private UserMapper userMapper;

    @Autowired
    private RoleMapper roleMapper;


    @Override
    public LoginRespDTO login(LoginReqDTO loginReqDTO) {
        LoginRespDTO loginRespDTO = new LoginRespDTO();
        UserDetails userDetails = loadUserByUsername(loginReqDTO.getUsername());
        if (ObjectUtil.isNull(userDetails)) {
            throw new RuntimeException("用户名或密码错误！");
        }
        loginRespDTO.setToken(JwtUtil.generateToken(userDetails));
        return loginRespDTO;
    }

    @Override
    public void add(UserDTO userDTO) {
        UserPO userPO = new UserPO();
        fillUser(userPO, userDTO, true);
        userMapper.insert(userPO);
    }

    private void fillUser(UserPO userPO, UserDTO userDTO, boolean isInsert) {
        userPO.setUsername(userDTO.getUsername());
        userPO.setPassword(userDTO.getPassword());
        userPO.setNickName(userDTO.getNickName());
        userPO.setGender(userDTO.getGender());
        userPO.setAvatar(userDTO.getAvatar());
        userPO.setMobile(userDTO.getMobile());
        userPO.setMail(userDTO.getMail());
        userPO.setRemark(userDTO.getRemark());
        userPO.setAvailable(userDTO.getAvailable());
        userPO.setLocked(userDTO.getLocked());
        userPO.setCreateTime(new Date());
        if (isInsert) {
            userPO.setCreateTime(new Date());
        }
        userPO.setUpdateTime(new Date());
    }

    @Override
    public void edit(UserDTO userDTO) {
        UserPO userPO = userMapper.selectById(userDTO.getId());
        fillUser(userPO, userDTO, false);
        userMapper.updateById(userPO);
    }

    @Override
    public void delete(List<Integer> idList) {
        // todo
    }

    @Override
    public UserDetails updatePassword(UserDetails user, String newPassword) {
        int update = userMapper.updatePassword(user.getUsername(), newPassword);
        if (update == 1) {
            ((UserPO) user).setPassword(newPassword);
        }
        return user;
    }

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        LambdaQueryWrapper<UserPO> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(UserPO::getUsername, username)
                .eq(UserPO::getAvailable, ENBool.TRUE.getValue());
        UserPO userPO = userMapper.selectOne(wrapper);
        if (ObjectUtil.isNull(userPO)) {
            throw new UsernameNotFoundException("用户不存在！");
        }
        List<RolePO> roleList = roleMapper.findRoleByUserId(userPO.getId());
        if (CollectionUtil.isNotEmpty(roleList)) {
            userPO.setRoleList(roleList);
            userPO.setAuthorities(AuthorityUtils.createAuthorityList(roleList.stream()
                    .map(RolePO::getName).toArray(String[]::new)));
        }
        return userPO;
    }
}




